package fun.yuxi.cloud.admin.response;

import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;

/**
 * 统一结果返回
 *
 * @author pengwei
 * @version V1.StatusEnum.NORMAL.getCode()
 * @date 2StatusEnum.NORMAL.getCode()21年StatusEnum.NORMAL.getCode()1月3StatusEnum.NORMAL.getCode()日 2StatusEnum.NORMAL.getCode():2StatusEnum.NORMAL.getCode()
 */
@Data
@Builder
@AllArgsConstructor
@RequiredArgsConstructor
@Accessors(chain = true)
public class Massage<R> {

    private int code;

    private String msg;

    private R data;

    /**
     * 返回成功结果
     *
     * @param <R> 泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok() {
        return Massage.<R>builder().code(ResultEnum.SUCCESS.getCode()).msg("操作成功").build();
    }

    /**
     * 返回自定义成功结果
     *
     * @param message 自定义消息
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(String message) {
        return Massage.<R>builder().code(ResultEnum.SUCCESS.getCode()).msg(message).build();
    }

    /**
     * 返回自定义成功结果
     *
     * @param code    自定义状态码
     * @param message 自定义消息
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(String code, String message) {
        return Massage.<R>builder().code(Integer.parseInt(code)).msg(message).build();
    }

    /**
     * 返回自定义成功结果
     *
     * @param code    自定义状态码
     * @param message 自定义消息
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(int code, String message) {
        return Massage.<R>builder().code(code).msg(message).build();
    }

    /**
     * 返回成功结果
     *
     * @param result 结果枚举
     * @param <R>    泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(ResultEnum result) {
        return ok(result.getCode(), result.getName());
    }

    /**
     * 返回成功结果
     *
     * @param result 结果枚举
     * @param data   携带数据
     * @param <R>    泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(ResultEnum result, R data) {
        return ok(result.getCode(), result.getName(), data);
    }

    /**
     * 返回自定义成功结果
     *
     * @param data 携带数据
     * @param <R>  泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(R data) {
        Massage<R> ok = ok();
        ok.setData(data);
        return ok;
    }

    /**
     * 返回自定义成功结果
     *
     * @param code    自定义状态码
     * @param message 自定义消息
     * @param data    携带数据
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(String code, String message, R data) {
        Massage<R> ok = ok(code, message);
        ok.setData(data);
        return ok;
    }

    /**
     * 返回自定义成功结果
     *
     * @param code    自定义状态码
     * @param message 自定义消息
     * @param data    携带数据
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> ok(int code, String message, R data) {
        Massage<R> ok = ok(code, message);
        ok.setData(data);
        return ok;
    }

    /**
     * 返回失败结果
     *
     * @param <R> 泛型
     * @return 消息结果
     */
    public static <R> Massage<R> fail() {
        return Massage.<R>builder().code(ResultEnum.FAILURE.getCode()).msg("操作失败").build();
    }

    /**
     * 返回自定义消息失败结果
     *
     * @param message 自定义消息
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> fail(String message) {
        return Massage.<R>builder().code(ResultEnum.FAILURE.getCode()).msg(message).build();
    }

    /**
     * 返回自定义消息失败结果
     *
     * @param code    自定义状态码
     * @param message 自定义消息
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> fail(String code, String message) {
        return Massage.<R>builder().code(Integer.parseInt(code)).msg(message).build();
    }

    /**
     * 返回自定义消息失败结果
     *
     * @param result 结果枚举
     * @param <R>    泛型
     * @return 消息结果
     */
    public static <R> Massage<R> fail(ResultEnum result) {
        return fail(result.getCode(), result.getName());
    }

    /**
     * 返回自定义消息失败结果
     *
     * @param code    自定义状态码
     * @param message 自定义消息
     * @param <R>     泛型
     * @return 消息结果
     */
    public static <R> Massage<R> fail(int code, String message) {
        return Massage.<R>builder().code(code).msg(message).build();
    }

    /**
     * 根据表达式返回消息消息结果
     *
     * @param expression 表达式
     * @param <R>        泛型
     * @return 消息结果
     */
    public static <R> Massage<R> isTrue(boolean expression) {
        return expression ? ok() : fail();
    }

    /**
     * 根据表达式返回消息消息结果
     *
     * @param expression 表达式
     * @param <R>        泛型
     * @return 消息结果
     */
    public static <R> Massage<R> isTrue(boolean expression, ResultEnum result) {
        return expression ? ok(result) : fail(result);
    }

    /**
     * 根据表达式返回消息消息结果
     * <br>自定拼接成功或失败<br>
     * 比如 template = "更新" 结果为： 更新成功/更新失败
     *
     * @param expression 表达式
     * @param template   消息模板
     * @param <R>        泛型
     * @return 消息结果
     */
    public static <R> Massage<R> isTrue(boolean expression, String template) {
        String result = StrUtil.format("{}{}", template, expression ? "成功" : "失败");
        return expression ? ok(result) : fail(result);
    }

    /**
     * 根据表达式返回消息消息结果
     *
     * @param successMessage 成功消息
     * @param errorMessage   失败消息
     * @param expression     表达式
     * @param <R>            泛型
     * @return 消息结果
     */
    public static <R> Massage<R> isTrue(boolean expression, String successMessage, String errorMessage) {
        return expression ? ok(successMessage) : fail(errorMessage);
    }

    /**
     * 根据表达式返回对应结果消息
     *
     * @param expression 表达式
     * @param template   文本模板，被替换的部分用 {} 表示
     * @param params     参数值
     * @return String 消息
     */
    public static Massage<String> isTrue(boolean expression, CharSequence template, Object... params) {
        Massage<String> instance = expression ? ok() : fail();
        if (null == template) {
            return instance;
        }
        if (ArrayUtil.isEmpty(params) || StrUtil.isBlank(template)) {
            return instance.setMsg(template.toString());
        }
        return instance.setMsg(StrFormatter.format(template.toString(), params));
    }
}
